#include "window.h"
#include <stdexcept>
#include "event/events.h"

namespace vkrender
{
    void VulkanWindow::framebuffer_resize_callback(GLFWwindow* window, int width, int height)
    {
        auto pWin = (VulkanWindow*)glfwGetWindowUserPointer(window);
        pWin->framebufferResized = true;
        pWin->width = width;
        pWin->height = height;

        // fire an event.
    }

    void VulkanWindow::mouse_move_callback(GLFWwindow* window, double xpos, double ypos)
    {

    }

    void VulkanWindow::mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
    {
        if (action != GLFW_RELEASE)
        {
            Event event;
            event.type = EventType::EVENT_BUTTON_PRESSED;
            event.context.data.u32[0] = button;
            event.handled = false;
            fire_event(event, nullptr);
        }
    }

    void VulkanWindow::key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
    {
        if (action != GLFW_RELEASE)
        {
            Event event;
            event.type = EventType::EVENT_KEY_PRESSED;
            event.context.data.u32[0] = key;
            event.handled = false;
            fire_event(event, nullptr);
        }
    }

    VulkanWindow::VulkanWindow(uint32_t w, uint32_t h, const std::string& name)
        : width(w), height(h), windowName(name)
    {
        init();
    }

    VulkanWindow::~VulkanWindow()
    {
        glfwDestroyWindow(window);
        glfwTerminate();
    }

    void VulkanWindow::init()
    {
        glfwInit();
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
        window = glfwCreateWindow(width, height, windowName.c_str(), nullptr, nullptr);
        glfwSetWindowUserPointer(window, this);
        glfwSetFramebufferSizeCallback(window, framebuffer_resize_callback);
        glfwSetMouseButtonCallback(window, mouse_button_callback);
        glfwSetCursorPosCallback(window, mouse_move_callback);
        glfwSetKeyCallback(window, key_callback);
    }

    VkExtent2D VulkanWindow::getExtent()
    {
        VkExtent2D ext;
        ext.width = width;
        ext.height = height;
        return ext;
    }

    void VulkanWindow::createWindowSurface(VkInstance instance, VkSurfaceKHR* surface)
    {
        if (glfwCreateWindowSurface(instance, window, nullptr, surface) != VK_SUCCESS)
        {
            throw std::runtime_error("failed to create window surface");
        }
    }


}
